package org.example.mock;

import com.github.javafaker.Faker;
import org.example.bean.SalesRecord;

import java.math.BigDecimal;
import java.sql.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class SalesRecordDataGenerator {
    private static final String DB_URL = "jdbc:mysql://hadoop102/bookstore?useSSL=false&requireSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "000000";
    private static final int BATCH_SIZE = 100;
    private static final Faker faker = new Faker(Locale.CHINA);
    private static final String[] EMPLOYEE_IDS = {"E1001", "E1002", "E2003", "E2004", "E3001", "E4001", "E5002"};

    public static void main(String[] args) {
        int count = 1000; // 默认生成1000条数据
        if (args.length >= 1) count = Integer.parseInt(args[0]);
        generateData(count);
    }

    public static void generateData(int count) {
        // 获取已有的店铺ID、图书ID和会员ID
        List<String> storeIds = fetchStoreIds();
        List<String> bookIds = fetchBookIds();
        List<String> memberIds = fetchMemberIds();

        if (storeIds.isEmpty() || bookIds.isEmpty()) {
            System.err.println("错误：请先生成店铺和图书数据");
            return;
        }

        List<SalesRecord> sales = new ArrayList<>();
        LocalDate today = LocalDate.now();

        for (int i = 0; i < count; i++) {
            String orderId = "O" + today.format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd")) +
                    String.format("%04d", faker.number().numberBetween(1, 9999));

            SalesRecord record = SalesRecord.builder()
                    .orderId(orderId)
                    .storeId(storeIds.get(faker.random().nextInt(storeIds.size())))
                    .bookId(bookIds.get(faker.random().nextInt(bookIds.size())))
                    .saleDate(today.minusDays(faker.number().numberBetween(0, 30)))
                    .saleTime(LocalTime.of(
                            faker.number().numberBetween(9, 21),
                            faker.number().numberBetween(0, 59)))
                    .quantity(faker.number().numberBetween(1, 5))
                    .unitPrice(BigDecimal.valueOf(faker.number().randomDouble(2, 20, 300)))
                    .totalAmount(BigDecimal.valueOf(faker.number().randomDouble(2, 20, 500)))
                    .paymentMethod(faker.number().numberBetween(1, 4))
                            .memberId(memberIds.isEmpty() || faker.random().nextBoolean() ?
                                    null : memberIds.get(faker.random().nextInt(memberIds.size())))
                            .employeeId(EMPLOYEE_IDS[faker.random().nextInt(EMPLOYEE_IDS.length)])
                            .createTime(LocalDateTime.now())
                            .build();
            sales.add(record);
        }

        insertData(sales);
    }

    private static List<String> fetchStoreIds() {
        List<String> ids = new ArrayList<>();
        String sql = "SELECT store_id FROM store_info";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                ids.add(rs.getString("store_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return ids;
    }

    private static List<String> fetchBookIds() {
        List<String> ids = new ArrayList<>();
        String sql = "SELECT book_id FROM book_info";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                ids.add(rs.getString("book_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return ids;
    }

    private static List<String> fetchMemberIds() {
        List<String> ids = new ArrayList<>();
        String sql = "SELECT member_id FROM member_info";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            while (rs.next()) {
                ids.add(rs.getString("member_id"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return ids;
    }

    private static void insertData(List<SalesRecord> sales) {
        String sql = "INSERT IGNORE INTO sales_record (order_id, store_id, book_id, sale_date, sale_time, " +
                "quantity, unit_price, total_amount, payment_method, member_id, employee_id, create_time) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            conn.setAutoCommit(false);
            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
                for (int i = 0; i < sales.size(); i++) {
                    SalesRecord record = sales.get(i);
                    pstmt.setString(1, record.getOrderId());
                    pstmt.setString(2, record.getStoreId());
                    pstmt.setString(3, record.getBookId());
                    pstmt.setDate(4, Date.valueOf(record.getSaleDate()));
                    pstmt.setTime(5, Time.valueOf(record.getSaleTime()));
                    pstmt.setInt(6, record.getQuantity());
                    pstmt.setBigDecimal(7, record.getUnitPrice());
                    pstmt.setBigDecimal(8, record.getTotalAmount());
                    pstmt.setInt(9, record.getPaymentMethod());
                    pstmt.setString(10, record.getMemberId());
                    pstmt.setString(11, record.getEmployeeId());
                    pstmt.setTimestamp(12, Timestamp.valueOf(record.getCreateTime()));
                    pstmt.addBatch();

                    if ((i + 1) % BATCH_SIZE == 0) pstmt.executeBatch();
                }
                pstmt.executeBatch();
                conn.commit();
                System.out.println("成功插入" + sales.size() + "条销售记录");
            } catch (SQLException e) {
                conn.rollback();
                e.printStackTrace();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}